﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;


namespace FightTheDragon.Managers
{
    class GlobalContentManager
    {
        // Class Members
        // The single instance of the GlobalContentManager
        private static GlobalContentManager m_Instance = new GlobalContentManager();

        // Resources
        private Dictionary<string, Texture2D> m_Textures;
        private Dictionary<string, SpriteFont> m_Fonts;
        private Dictionary<string, SoundEffect> m_Sounds;
        private Dictionary<string, Song> m_Music;


        private Vector2 m_CrashAmount;
        private float m_fSoundVolume;
        private float m_fMusicVolume;

        // RNG
        private Random m_Random;

        // Assigned to in SamShin constructor
        private GraphicsDeviceManager m_Graphics;
        private ContentManager m_Content;

        // Assigned to in SamShin LoadContent
        private SpriteBatch m_spriteBatch;

        

        public ContentManager Content
        {
            get { return m_Content; }
            set { m_Content = value; }
        }

        public SpriteBatch Sprites
        {
            get { return m_spriteBatch; }
            set { m_spriteBatch = value; }
        }

        public GraphicsDeviceManager Graphics
        {
            get { return m_Graphics; }
            set { m_Graphics = value; }
        }

        public Vector2 Crash
        {
            get { return m_CrashAmount; }
            set { m_CrashAmount = value; }
        }

        public Vector2 ScreenSize
        {
            get { return new Vector2(Graphics.GraphicsDevice.Viewport.Width, Graphics.GraphicsDevice.Viewport.Height); }
        }

        public float SoundVolume
        {
            get { return m_fSoundVolume; }
            set { m_fSoundVolume = value; }
        }

        public float MusicVolume
        {
            get { return m_fMusicVolume; }
            set { m_fMusicVolume = value; }
        }

        // Access to single instance of this class
        public static GlobalContentManager Instance
        {
            get { return m_Instance; }
        }

        ///////////////////////////////////////////////////////////
        // Constructor
        ///////////////////////////////////////////////////////////
        private GlobalContentManager()
        {
            m_Textures = new Dictionary<string, Texture2D>();
            m_Fonts = new Dictionary<string, SpriteFont>();
            m_Sounds = new Dictionary<string, SoundEffect>();
            m_Music = new Dictionary<string, Song>();
            m_Random = new Random();
           
        }

        ///////////////////////////////////////////////////////////
        // Texture
        ///////////////////////////////////////////////////////////
        public Texture2D Texture(string szTextureName)
        {
            Texture2D tempTex;
            if (m_Textures.TryGetValue(szTextureName, out tempTex) == true)
            {
                return tempTex;
            }
            else
            {
                tempTex = Content.Load<Texture2D>(szTextureName);
                m_Textures.Add(szTextureName, tempTex);
                return tempTex;
            }
        }

        ///////////////////////////////////////////////////////////
        // Font
        ///////////////////////////////////////////////////////////
        public SpriteFont Font(string szFontName)
        {
            SpriteFont tempFont;
            if (m_Fonts.TryGetValue(szFontName, out tempFont) == true)
            {
                return tempFont;
            }
            else
            {
                tempFont = Content.Load<SpriteFont>(szFontName);
                m_Fonts.Add(szFontName, tempFont);
                return tempFont;
            }
        }

        ///////////////////////////////////////////////////////////
        // Sound
        ///////////////////////////////////////////////////////////
        public SoundEffect Sound(string szSoundName)
        {
            SoundEffect tempSound;
            if (m_Sounds.TryGetValue(szSoundName, out tempSound) == true)
            {
                return tempSound;
            }
            else
            {
                tempSound = Content.Load<SoundEffect>(szSoundName);
                m_Sounds.Add(szSoundName, tempSound);
                return tempSound;
            }
        }

        ///////////////////////////////////////////////////////////
        // Music
        ///////////////////////////////////////////////////////////
        public Song Music(string szMusicName)
        {
            Song tempMusic;
            if (m_Music.TryGetValue(szMusicName, out tempMusic) == true)
            {
                return tempMusic;
            }
            else
            {
                tempMusic = Content.Load<Song>(szMusicName);
                m_Music.Add(szMusicName, tempMusic);
                return tempMusic;
            }
        }

        ///////////////////////////////////////////////////////////
        // Animation
        ///////////////////////////////////////////////////////////


        ///////////////////////////////////////////////////////////
        // SafeRect (Rectangle)
        ///////////////////////////////////////////////////////////
        public Rectangle SafeRect(Rectangle _rRect)
        {
            Rectangle rTest = Graphics.GraphicsDevice.Viewport.TitleSafeArea;
            Rectangle rOutput = _rRect;

            if (rOutput.X < rTest.X)
                rOutput.X = rTest.X;
            if (rOutput.X + rOutput.Width > rTest.X + rTest.Width)
                rOutput.X -= Graphics.PreferredBackBufferWidth - rTest.X - rTest.Width;

            if (rOutput.Y < rTest.Y)
                rOutput.Y += rTest.Y;
            if (rOutput.Y + rOutput.Height > rTest.Y + rTest.Height)
                rOutput.Y -= Graphics.PreferredBackBufferHeight - rTest.Y - rTest.Height;

            rOutput.Width = _rRect.Width;
            rOutput.Height = _rRect.Height;

            return rOutput;
        }

        ///////////////////////////////////////////////////////////
        // SafeString (Font)
        ///////////////////////////////////////////////////////////
        public Vector2 SafeRect(Vector2 _vPos, SpriteFont _fFont, String _szString)
        {
            Rectangle rOutput = new Rectangle((int)_vPos.X, (int)_vPos.Y, (int)_fFont.MeasureString(_szString).X,
                (int)_fFont.MeasureString(_szString).Y);
            rOutput = SafeRect(rOutput);

            return new Vector2(rOutput.X, rOutput.Y);
        }



        ///////////////////////////////////////////////////////////
        // RandomInt
        ///////////////////////////////////////////////////////////
        public int RandomInt(int _nMin, int _nMax)
        {
            return m_Random.Next(_nMin, _nMax);
        }

        ///////////////////////////////////////////////////////////
        // RandomFloat
        ///////////////////////////////////////////////////////////
        public float RandomFloat(float _fMin, float _fMax)
        {
            return ((float)(m_Random.Next((int)_fMin * 1000, (int)_fMax * 1000)) / 1000.0f);
        }

        ///////////////////////////////////////////////////////////
        // RandomBool
        ///////////////////////////////////////////////////////////
        public bool RandomBool()
        {
            return (m_Random.Next(0, 100) >= 50);
        }

        ///////////////////////////////////////////////////////////
        // Shutdown
        ///////////////////////////////////////////////////////////
        public void Shutdown()
        {
            Dictionary<string, Texture2D>.ValueCollection textures = m_Textures.Values;
            foreach (Texture2D idx in textures)
            {
                idx.Dispose();
            }
            m_Textures.Clear();

            Dictionary<string, SoundEffect>.ValueCollection sounds = m_Sounds.Values;
            foreach (SoundEffect idx in sounds)
            {
                idx.Dispose();
            }
            m_Sounds.Clear();

            Dictionary<string, Song>.ValueCollection musics = m_Music.Values;
            foreach (Song idx in musics)
            {
                idx.Dispose();
            }
            m_Music.Clear();

           

            m_Fonts.Clear();

            m_spriteBatch.Dispose();

            Content.Dispose();
        }

 

        ///////////////////////////////////////////////////////////
        // FloatsAreEqual
        ///////////////////////////////////////////////////////////
        public bool FloatsAreEqual(float _f1, float _f2)
        {
            float _epsilon = 0.01f;
            if (Math.Abs(_f1 - _f2) <= _epsilon)
                return true;
            return false;
        }

        ///////////////////////////////////////////////////////////
        // FloatsAreEqual
        ///////////////////////////////////////////////////////////
        public bool FloatsAreEqual(float _f1, float _f2, float _epsilon)
        {
            if (Math.Abs(_f1 - _f2) <= _epsilon)
                return true;
            return false;
        }
    }
}
